package com.zenchn.controller;

import com.zenchn.annotation.OperLog;
import com.zenchn.entity.AuthTreeVO;
import com.zenchn.entity.HttpDataResult;
import com.zenchn.entity.TSysAuthorityVO;
import com.zenchn.enums.DictTypeEnum;
import com.zenchn.enums.OperLogActionEnum;
import com.zenchn.exception.CheckException;
import com.zenchn.model.TSysAuthority;
import com.zenchn.model.TSysAuthorityExample;
import com.zenchn.model.TSysDict;
import com.zenchn.model.TSysOauthClient;
import com.zenchn.service.AuthorityService;
import com.zenchn.service.DictService;
import com.zenchn.service.OauthClientService;
import com.zenchn.utils.AuthUtils;
import com.zenchn.utils.CommonUtils;
import io.swagger.annotations.*;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 异步 菜单功能权限相关 控制层
 *
 * @author dingxinfa
 * @date 2020-04-20
 */
@RestController
@RequestMapping(value = "auth")
@Api(value = "菜单功能权限模块接口", tags = "系统管理-菜单权限")
@RequiresPermissions("menu:auth")
public class AuthorityController {

    private final String MODULE = "系统管理>菜单权限";

    @Resource
    private AuthorityService authorityService;

    @Resource
    private OauthClientService oauthClientService;

    @Resource
    private DictService dictService;


    /**
     * 菜单权限数据列表
     *
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.QUERY, detail = "获取全部功能权限列表", isSaveRequestData = false)
    @ApiOperation(value = "菜单权限数据列表", notes = "菜单权限数据列表")
    @GetMapping(value = "/list")
    @RequiresPermissions("menu:auth")
    public ResponseEntity<HttpDataResult<List<TSysAuthorityVO>>> list(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<List<TSysAuthorityVO>> result = new HttpDataResult<>(request.getRequestURI());

        List<TSysAuthorityVO> authorityVOList = authorityService.selectCascadeAuthList();

        result.setData(authorityVOList);

        result.setMessage("获取权限列表成功.");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }


    /***
     * 新增权限UI数据接口
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.QUERY, detail = "新增权限UI数据接口", isSaveRequestData = false)
    @ApiOperation(value = "新增权限UI数据接口", notes = "新增权限UI数据接口")
    @GetMapping(value = "/add")
    @RequiresPermissions("menu:auth:add")
    public ResponseEntity<HttpDataResult<Map<String, Object>>> add(
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<Map<String, Object>> result = new HttpDataResult<>(request.getRequestURI());
        Map<String, Object> resultData = new HashMap<>(16);

        List<TSysOauthClient> oauthClientList = oauthClientService.selectByExample(null);
        List<TSysDict> authTypeList = dictService.selectByDictTypeId(DictTypeEnum.AUTH_TYPE_GROUP.getId());

        resultData.put("oauthClientList", oauthClientList);
        resultData.put("authTypeList", authTypeList);
        result.setData(resultData);

        result.setMessage("OK");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }

    /**
     * 新增权限保存提交
     *
     * @param auth
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.INSERT, detail = "新增权限保存提交", isSaveRequestData = true)
    @ApiOperation(value = "新增权限保存提交", notes = "新增权限保存提交")
    @ApiParam(type = "TSysAuthority",name = "auth", value = "系统权限对象", required = true)
    @PostMapping(value = "/addSubmit")
    @RequiresPermissions("menu:auth:add")
    public ResponseEntity<HttpDataResult<String>> addSubmit(
            @RequestBody @Valid TSysAuthority auth, BindingResult results,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (results.hasErrors()){
            throw new CheckException(Objects.requireNonNull(results.getFieldError()).getDefaultMessage());
        }
        if (!authorityService.verifyAuthSign(auth.getAuthId(),auth.getAuthSign())){
            throw new CheckException("权限标识重复，无法新增提交！");
        }
        HttpDataResult<String> result = new HttpDataResult<>(request.getRequestURI());

        //初始化权限层级信息
        initAnthLevel(auth);

        auth.setCreateTime(LocalDateTime.now());
        auth.setAuthId(CommonUtils.randomUUID());
        authorityService.insert(auth);

        result.setData(auth.getAuthId());

        result.setMessage("新增权限成功。");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);

    }

    /**
     * 初始化权限层级信息
     *
     * @param auth
     */
    private void initAnthLevel(TSysAuthority auth) {
        if (null != auth.getParentId() && !"".equals(auth.getParentId().trim())) {
            TSysAuthority pAuth = authorityService.selectByPrimaryKey(auth.getParentId());
            if (null!=pAuth) {
                auth.setAuthLevel(pAuth.getAuthLevel() + 1);
            } else {
                auth.setAuthLevel(1);
                auth.setParentId(null);
            }
        } else {
            auth.setAuthLevel(1);
            auth.setParentId(null);
        }
    }

    /***
     * 修改权限
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.QUERY, detail = "修改权限UI数据接口", isSaveRequestData = true)
    @ApiOperation(value = "修改权限UI数据接口", notes = "修改权限UI数据接口")
    @ApiImplicitParam(dataType = "String", name = "authId", value = "权限ID", required = true)
    @GetMapping(value = "/modify")
    public ResponseEntity<HttpDataResult<Map<String, Object> >> modify(
            @RequestParam(value = "authId") String authId,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<Map<String, Object>> result = new HttpDataResult<>(request.getRequestURI());
        Map<String, Object> resultData = new HashMap<>(16);

        TSysAuthority auth = authorityService.selectByPrimaryKey(authId);
        resultData.put("auth", auth);

        //获取父级路径
        if (null != auth.getParentId() && !"".equals(auth.getParentId().trim())) {
            List<TSysAuthority> fullCascadeList = authorityService.findFullCascade(auth.getParentId());

            resultData.put("parentAuthIdList", fullCascadeList.stream().map(TSysAuthority::getAuthId).collect(Collectors.toList()));
        }

        List<TSysOauthClient> oauthClientList = oauthClientService.selectByExample(null);
        List<TSysDict> authTypeList = dictService.selectByDictTypeId(DictTypeEnum.AUTH_TYPE_GROUP.getId());

        resultData.put("oauthClientList", oauthClientList);
        resultData.put("authTypeList", authTypeList);

        result.setData(resultData);
        result.setMessage("OK");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }


    /**
     * 修改权限保存提交
     *
     * @param auth
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.UPDATE, detail = "修改权限保存提交", isSaveRequestData = true)
    @ApiOperation(value = "修改权限保存提交", notes = "修改权限保存提交")
    @ApiParam(type = "TSysAuthority",name = "auth", value = "系统权限对象", required = true)
    @PutMapping(value = "/modifySubmit")
    @RequiresPermissions("menu:auth:modify")
    public ResponseEntity<HttpDataResult<String>> modifySubmit(
            @RequestBody @Valid TSysAuthority auth, BindingResult results,
            HttpServletRequest request, HttpServletResponse response) throws Exception {

        if (results.hasErrors()){
            throw new CheckException(Objects.requireNonNull(results.getFieldError()).getDefaultMessage());
        }

        if (!authorityService.verifyAuthSign(auth.getAuthId(),auth.getAuthSign())){
            throw new CheckException("权限标识重复，无法修改保存！");
        }

        HttpDataResult<String> result = new HttpDataResult<>(request.getRequestURI());

        //初始化权限层级信息
        initAnthLevel(auth);

        if (auth.getAuthId().equals(auth.getParentId())) {
            auth.setAuthLevel(1);
            auth.setParentId(null);
        }
        authorityService.updateByPrimaryKeySelective(auth);

        result.setData(auth.getAuthId());

        result.setMessage("修改权限成功。");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);
    }


    /**
     * 按照客户端类型获取权限菜单树
     *
     * @param authId        当前编辑权限ID
     * @param oauthClientId 客户端类型ID
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.QUERY, detail = "按照客户端类型获取权限菜单树", isSaveRequestData = true)
    @ApiOperation(value = "按照客户端类型获取权限菜单树", notes = "按照客户端类型获取权限菜单树")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "oauthClientId", value = "客户端类型ID", required = true),
            @ApiImplicitParam(dataType = "String", name = "authId", value = "当前编辑权限ID", required = false)
    })
    @GetMapping(value = "/getAuthTree")
    public ResponseEntity<HttpDataResult<List<AuthTreeVO>>> getAuthTree(
            @RequestParam(value = "oauthClientId") String oauthClientId,
            @RequestParam(required = false, value = "authId") String authId,
            HttpServletRequest request, HttpServletResponse response) throws Exception {

        HttpDataResult<List<AuthTreeVO>> result = new HttpDataResult<>(request.getRequestURI());

        Map<String, Object> map = new HashMap<>(16);

        TSysAuthorityExample example = new TSysAuthorityExample();
        TSysAuthorityExample.Criteria criteria = example.createCriteria();
        criteria.andOauthClientIdEqualTo(oauthClientId);

        if (null != authId && !"".equals(authId.trim())) {
            criteria.andAuthIdNotEqualTo(authId.trim());
        }

        List<TSysAuthority> authorityList = authorityService.selectByExample(example);

        result.setData(AuthUtils.treeBuilder(authorityList));

        result.setMessage("按照客户端类型获取权限菜单树成功.");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);

    }


    /***
     * 验证   权限标识  唯一性
     * @param authId
     * @param authSign
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @OperLog(module = MODULE, action = OperLogActionEnum.CHECK, detail = "验证权限标识唯一性", isSaveRequestData = true)
    @ApiOperation(value = "验证权限标识唯一性", notes = "验证权限标识唯一性")
    @ApiImplicitParams({
            @ApiImplicitParam(dataType = "String", name = "authId", value = "权限ID", required = false),
            @ApiImplicitParam(dataType = "String", name = "authSign", value = "权限标识", required = true)
    })
    @GetMapping(value = "/verifyAuthSign")
    public ResponseEntity<HttpDataResult<Boolean>> verifyAuthSign(
            @RequestParam(required = false, value = "authId") String authId,
            @RequestParam(value = "authSign") String authSign,
            HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpDataResult<Boolean> result = new HttpDataResult<>(request.getRequestURI());

        result.setData(authorityService.verifyAuthSign(authId,authSign));


        result.setMessage("验证权限标识唯一性成功.");
        result.setStatus(HttpStatus.OK.value());
        return new ResponseEntity<>(result, HttpStatus.OK);

    }

}
